#!/usr/bin/env python
from twisted.conch.telnet import Telnet
from twisted.internet.protocol import ReconnectingClientFactory, ClientFactory
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.internet import defer
import twisted.conch.telnet as telnet
import sys, struct

AUTH = chr(37)
SerToCli = 1
CliToServ = 0
UNK = 2

def getTerminalSize():
    import os
    env = os.environ
    def ioctl_GWINSZ(fd):
        try:
            import fcntl, termios, struct, os
            cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
        '1234'))
        except:
            return
        return cr
    cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
    if not cr:
        try:
            fd = os.open(os.ctermid(), os.O_RDONLY)
            cr = ioctl_GWINSZ(fd)
            os.close(fd)
        except:
            pass
    if not cr:
        cr = (env.get('LINES', 25), env.get('COLUMNS', 80))

        ### Use get(key[, default]) instead of a try/catch
        #try:
        #    cr = (env['LINES'], env['COLUMNS'])
        #except:
        #    cr = (25, 80)
    Lineas = int(cr[0])
    Columnas = int(cr[1])
    #return int(cr[1]), int(cr[0])
    return Lineas, Columnas 

class MyTelnetProtocol(Telnet):
    LocalEnable = [telnet.ECHO, telnet.SGA, telnet.NAWS, telnet.NULL] #OPCION QUE SE REMUVA DE AQUI NO APARECERA EN US
    LocalDisable = [AUTH]
    ComunicationStatus = UNK
    
#    def __TelnetEngineDesicion(self):
#        self.responseList= []
##        s = self.getOptionState('\x01')
##        print 'US ',s.us.state ,s.us.negotiating
##        print 'HIM', s.him.state, s.him.negotiating
##        for i in iter(self.options):
##            if i == telnet.ECHO:
##                s = self.getOptionState(i)
##                print "HIM state: %s & negotiating: %s\n" % (s.him.state, s.him.negotiating)
##                if (s.him.state == 'yes' and s.him.negotiating == False):
##                    print "Echo vamos a enviar un DO"
##                    print "US state: %s & negotiating: %s\n" % (s.us.state, s.us.negotiating)
###                    self.responseList.append(self.telnet_DO(i))
##                if i == telnet.NULL:
##                    pass
#    
#    def __LocalEnableAdd(self, element):
#        self.LocalEnable.append(element)
#    
#    def connectionMade(self):
#        Telnet.connectionMade(self)
        
    def enableLocal(self, option):
        return option in self.LocalEnable
    
    def disableRemote(self, option):
        Telnet.disableRemote(self, option)
        return option in self.LocalDisable
    
    def enableRemote(self, option):
        return True
        
    def applicationDataReceived(self, bytes):
        print bytes
       
    def dataReceived(self, data):
        Telnet.dataReceived(self, data)
#        print "Data received"
#        print self.options
        self.ComunicationStatus = SerToCli
#        if data[0] != telnet.IAC:
#            print data
        #self.__TelnetEngineDesicion()
        
#    def telnet_WILL(self, option):
#        Telnet.telnet_WILL(self, option)
        
            
    def telnet_DO(self,option):
        Telnet.telnet_DO(self, option)
        if option == telnet.NAWS:
#            print "Request subnegotiation"
            lin, cols = getTerminalSize()
            self.requestNegotiation(telnet.NAWS, struct.pack('hh', lin,cols))

class MyTelnetFactory(ClientFactory):
    protocol = MyTelnetProtocol

    def __init__(self, Deferred):
        self.deffered = Deferred
    
    def DefPrintHelo(self):
        print "helo"
    
    def clientConnectionLost(self, conector, ureason):
        print "Hemos perdido conexion con el cliente"
#        ReconnectingClientFactory.clientConnectionLost(self, conector, ureason)
        
    def clientConnectionFailed(self, connector, reason):
        print "Houston tenemos un problema"
#        ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
    
    def WriteOneTime(self, data):
        self.protocol.transport.write(data)

if __name__ == '__main__':
    from twisted.internet import reactor
    
    def TestProtocol(MyProtocolsTest):
        print "TestProtocols"
        testunit = MyProtocolsTest
        #reactor.callLater(5, testunit.clearBuffer)
        #print "Limpiamos"
        #reactor.callLater(10, testunit.write, 'dir')
    
    host = '192.168.213.143'
    port = 23
    client = TCP4ClientEndpoint(reactor, host, port)  
    #reactor.connectTCP(host, port, MyTelnetFactory())
    d = defer.Deferred()
    factory = MyTelnetFactory(d)
    reactor.connectTCP(host, port, factory)
    print "aqui"
    #d = client.connect(MyTelnetFactory())
    d.addCallback(TestProtocol)
    reactor.run()